\documentclass[a4paper,12pt]{report}
\usepackage[a4paper, top=3cm, bottom=3cm, left=2.5cm, right=2.5cm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage{titlesec}
\usepackage{times}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{pdfpages}
\usepackage[absolute]{textpos}
\usepackage{setspace}
\usepackage{titletoc}
\usepackage[backend=biber,language=czech]{biblatex}
\usepackage[czech]{babel}
\usepackage[section]{placeins}

\usepackage{pdflscape}

\usepackage{pgfplots}

\usepackage{dirtree}
\usepackage{hyperref}
\hypersetup{
    colorlinks=true,
    linkcolor=blue,
    filecolor=magenta,      
    urlcolor=cyan,
    pdftitle={Overleaf Example},
    pdfpagemode=FullScreen,
    }

% Chapter title format
\titleformat{\chapter}
  {\normalfont\fontsize{18}{21}\bfseries}{\thechapter.}{1em}{}
\titlespacing{\chapter}{0cm}{0cm}{1cm}

% Section title format
\titleformat{\section}
  {\normalfont\fontsize{15}{18}\bfseries}{\thesection}{1em}{}

% For sections before table of contents
\newcommand{\unnumberedsection}[1]{%
  \section*{#1}%
}

% For section numbering
\setcounter{secnumdepth}{3}
\setcounter{tocdepth}{\value{secnumdepth}}

% Code formatting
\definecolor{codegreen}{rgb}{0,0.6,0}
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
\definecolor{codepurple}{rgb}{0.58,0,0.82}
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
\lstdefinestyle{code_style}{
    backgroundcolor=\color{backcolour},   
    commentstyle=\color{codegreen},
    keywordstyle=\color{magenta},
    numberstyle=\tiny\color{codegray},
    stringstyle=\color{codepurple},
    basicstyle=\ttfamily\footnotesize,
    breakatwhitespace=false,         
    breaklines=true,                 
    captionpos=b,                    
    keepspaces=true,                 
    numbers=left,                    
    numbersep=5pt,                  
    showspaces=false,                
    showstringspaces=false,
    showtabs=false,                  
    tabsize=2,
    literate =        % Support additional characters
      {á}{{\'a}}1  {é}{{\'e}}1  {í}{{\'i}}1 {ó}{{\'o}}1  {ú}{{\'u}}1
      {Á}{{\'A}}1  {É}{{\'E}}1  {Í}{{\'I}}1 {Ó}{{\'O}}1  {Ú}{{\'U}}1
      {à}{{\`a}}1  {è}{{\`e}}1  {ì}{{\`i}}1 {ò}{{\`o}}1  {ù}{{\`u}}1
      {À}{{\`A}}1  {È}{{\`E}}1  {Ì}{{\`I}}1 {Ò}{{\`O}}1  {Ù}{{\`U}}1
      {ä}{{\"a}}1  {ë}{{\"e}}1  {ï}{{\"i}}1 {ö}{{\"o}}1  {ü}{{\"u}}1
      {Ä}{{\"A}}1  {Ë}{{\"E}}1  {Ï}{{\"I}}1 {Ö}{{\"O}}1  {Ü}{{\"U}}1
      {â}{{\^a}}1  {ê}{{\^e}}1  {î}{{\^i}}1 {ô}{{\^o}}1  {û}{{\^u}}1
      {Â}{{\^A}}1  {Ê}{{\^E}}1  {Î}{{\^I}}1 {Ô}{{\^O}}1  {Û}{{\^U}}1
      {œ}{{\oe}}1  {Œ}{{\OE}}1  {æ}{{\ae}}1 {Æ}{{\AE}}1  {ß}{{\ss}}1
      {ẞ}{{\SS}}1  {ç}{{\c{c}}}1 {Ç}{{\c{C}}}1 {ø}{{\o}}1  {Ø}{{\O}}1
      {å}{{\aa}}1  {Å}{{\AA}}1  {ã}{{\~a}}1  {õ}{{\~o}}1 {Ã}{{\~A}}1
      {Õ}{{\~O}}1  {ñ}{{\~n}}1  {Ñ}{{\~N}}1  {¿}{{?`}}1  {¡}{{!`}}1
      {°}{{\textdegree}}1 {º}{{\textordmasculine}}1 {ª}{{\textordfeminine}}1
      {£}{{\pounds}}1  {©}{{\copyright}}1  {®}{{\textregistered}}1
      {«}{{\guillemotleft}}1  {»}{{\guillemotright}}1  {Ð}{{\DH}}1  {ð}{{\dh}}1
      {Ý}{{\'Y}}1    {ý}{{\'y}}1    {Þ}{{\TH}}1    {þ}{{\th}}1    {Ă}{{\u{A}}}1
      {ă}{{\u{a}}}1  {Ą}{{\k{A}}}1  {ą}{{\k{a}}}1  {Ć}{{\'C}}1    {ć}{{\'c}}1
      {Č}{{\v{C}}}1  {č}{{\v{c}}}1  {Ď}{{\v{D}}}1  {ď}{{\v{d}}}1  {Đ}{{\DJ}}1
      {đ}{{\dj}}1    {Ė}{{\.{E}}}1  {ė}{{\.{e}}}1  {Ę}{{\k{E}}}1  {ę}{{\k{e}}}1
      {Ě}{{\v{E}}}1  {ě}{{\v{e}}}1  {Ğ}{{\u{G}}}1  {ğ}{{\u{g}}}1  {Ĩ}{{\~I}}1
      {ĩ}{{\~\i}}1   {Į}{{\k{I}}}1  {į}{{\k{i}}}1  {İ}{{\.{I}}}1  {ı}{{\i}}1
      {Ĺ}{{\'L}}1    {ĺ}{{\'l}}1    {Ľ}{{\v{L}}}1  {ľ}{{\v{l}}}1  {Ł}{{\L{}}}1
      {ł}{{\l{}}}1   {Ń}{{\'N}}1    {ń}{{\'n}}1    {Ň}{{\v{N}}}1  {ň}{{\v{n}}}1
      {Ő}{{\H{O}}}1  {ő}{{\H{o}}}1  {Ŕ}{{\'{R}}}1  {ŕ}{{\'{r}}}1  {Ř}{{\v{R}}}1
      {ř}{{\v{r}}}1  {Ś}{{\'S}}1    {ś}{{\'s}}1    {Ş}{{\c{S}}}1  {ş}{{\c{s}}}1
      {Š}{{\v{S}}}1  {š}{{\v{s}}}1  {Ť}{{\v{T}}}1  {ť}{{\v{t}}}1  {Ũ}{{\~U}}1
      {ũ}{{\~u}}1    {Ū}{{\={U}}}1  {ū}{{\={u}}}1  {Ů}{{\r{U}}}1  {ů}{{\r{u}}}1
      {Ű}{{\H{U}}}1  {ű}{{\H{u}}}1  {Ų}{{\k{U}}}1  {ų}{{\k{u}}}1  {Ź}{{\'Z}}1
      {ź}{{\'z}}1    {Ż}{{\.Z}}1    {ż}{{\.z}}1    {Ž}{{\v{Z}}}1  {ž}{{\^z}}1
      {Ž}{{\^Z}}1
}
\lstset{style=code_style}

% Document metadata
\title{Branch Brawl - multiplayer 3D hra}
\author{Jan Skládal\\4.A\\ Informační technologie (18-20-M/01)\\}
\date{2023/2024}

% Citations
\addbibresource{references.bib}

% Temporarly switch off page numbering
\pagenumbering{gobble}

% Title page
\begin{document}
\onehalfspacing 
\linespread{1.125}
\begin{textblock}{7}(4.5,1)
\begin{center}
\noindent \normalsize DELTA - Střední škola informatiky a ekonomie, s.r.o.\\Ke Kamenci 151, Pardubice
\end{center}
\end{textblock}
\maketitle

% Assignment
\includepdf[pages=-]{pdfs/zadani.pdf}

\unnumberedsection{Prohlášení}
Prohlašuji, že jsem maturitní projekt vypracoval(a) samostatně, výhradně s použitím uvedené
literatury.\\
\\
V Pardubicích dne 31.3.2024 ...................................

% Acknowledgements
\pagebreak
\unnumberedsection{Poděkování}
Upřímně děkuji panu Mgr. Janu Mottlovi za odborné vedení maturitní práce a za rady při tvorbě projektu.
\pagebreak

% Resumé
\pagebreak

\unnumberedsection{Anotace}
Tato dokumentace popisuje vývoj 3D hry pro více hráčů a problematiku, se kterou se můžete v rámci multiplayer her setkat. Obsahuje popis samotné hry, implementaci, strukturu projektu, různé algoritmy a obsáhlý seznam grafických děl.

\unnumberedsection{Klíčová slova}

C\#, Unity Engine, Hra pro více hráčů, 3D grafika, TPS

\unnumberedsection{Annotation}
This documentation describes the development of a 3D multiplayer game and the issues that you may encounter in multiplayer games. It contains a description of the game itself, the implementation, the structure of the project, the various algorithms and a comprehensive list of the graphical assets.

\unnumberedsection{Keywords}

C\#, Unity Engine, Multiplayer game, 3D graphics, TPS

\pagebreak

% Acknowledgements
\pagebreak
\renewcommand{\contentsname}{\centering Obsah}
\tableofcontents
\pagebreak

% From this point onwards, switch on page numbering
\pagenumbering{arabic}
\setcounter{page}{1}
\setcounter{section}{1}

% Content

\chapter*{Úvod}

Videoherní průmysl v dnešní době tvoří nepostradatelnou součást naší kultury s více než 3 miliardami hráčů v roce 2023 \cite{financesonline-gamers}. Není proto divu, že tento průmysl vzrostl na průmysl multimiliardový.\\

Takovým dětským snem každého hráče, který na hrách vyrůstal, je si kromě hraní i nějakou hru také vytvořit. Minimálně to tak bylo i v mém případě, a když se bavíme o dětském snu, dostáváme se k myšlence. K myšlence, která tento projekt vytváří.\\

Nápadem bylo vzít hráče zpět do dětství a rozpomenout si na dobu, kdy jako dítě jste na zahradě a naleznete klacek. Není to ale ledajaký klacek. Tento klacek až moc podobně připomíná střelnou zbraň! Jako dítě vás hned začínají napadat všelijaké scénáře, kdy se objevíte například uprostřed bojového pole, a právě tento klacek vám tvoří vašeho silného, střely střílejícího parťáka. Co kdybych vám ale řekl, že nyní tento svět nezůstává pouze ve světě dětské fantazie, ale přenáší se do vašich herních obrazovek! A přesně o tom je hra Branch Brawl.\\

Cílem tohoto projektu je vypořádat se s výzvou herního vývoje a naučit se pracovat s nástroji k tomuto účelu dostupnými. Zjistit nejen jak se hry vyvíjí, ale jaký je celý proces za vytvářením vlastního vymyšleného světa, následného usazení konceptu hry, který do tohoto světa bude zapadat, a k tomu ty již vymyšlené herní koncepty z myšlenek přetáhnout do reality a reálně tyto systémy implementovat, a to vše bez jakékoliv předchozí zkušenosti v tomto směru. A aby to nebylo vše, pochopit koncept multiplayer her a jejich implementace a vše na závěr zaobalit do vlastnoručně tvořeného grafického vizuálu.\\



\chapter{Teoretická část}

\section{Topologie sítí u multiplayer her}

V nejen herním, ale obecně ve světě počítačových sítí pracujeme ze základu s 2 modely síťového propojení.\cite{itnetwork-zaklady-site}
\begin{itemize}
    \item Server - Klient
    \item Peer to Peer (P2P)
\end{itemize}

\subsection{Topologie Server - Klient}
Server-klient model je jedním z nejběžnějších přístupů k implementaci multiplayer her. Je ideální pokud je požadována stabilita a bezpečnost, proto je využíván u většiny světových herních titulů jakými může být například League of Legends, CS:GO, Minecraft a další.\\

Tato topologie závisí na existenci 1 dedikovaného serveru, na který se následně klienti napojí. V tomto modelu veškerá komunikace prochází právě přes tento dedikovaný server, a to nám umožňuje veškerou komunikaci na serveru monitorovat.\cite{unitynetworktopo}\cite{networktopo2}\\

\textbf{Výhody:}
\begin{itemize}
    \item Centrální autorita: V server-klient modelu slouží server jako centrální autorita, která řídí herní logiku a udržuje konzistenci stavu hry mezi všemi hráči. To zajišťuje, že veškeré akce a události v hře jsou synchronizované a správně interpretované všemi účastníky.
    \item Bezpečnost a integrita dat: Centrální server umožňuje implementaci bezpečnostních opatření pro kontrolu nad proudícími daty. To dělá obtížnější vytvářet podvodné modifikace a provádět manipulaci nad zasílanými údaji.
    \item Lepší řízení výkonu a zátěže vůči klientovi: Model umožňuje více možností pro optimalizaci výkonu, která přetahuje zátěž z klienta na server. Vytváříme tak lehčí klienty.
\end{itemize} 

\textbf{Nevýhody:}
\begin{itemize}
    \item Závislost na serveru: Pro provoz tohoto modelu je potřeba aby běžel stabilní a spolehlivý server. Pokud hráčům neumožňujeme spouštět vlastní instance serveru, tak budeme vždy omezováni v počtu maximálního počtu hráčů určeného výkonem a množstvím vlastněných serverů.
    \item Náročnější implementace: Tento model pro nás znamená, že musíme místo 1 univerzálního programu vytvářet programy 2. Jeden který bude sloužit jako serverový program a druhý právě ve formě klienta, který následně budeme distribuovat mezi hráče.
    \item Nákladné na provoz: Mít neustále spuštěný server pro provoz je nákladné.
\end{itemize}

\subsection{Topologie Peer to Peer (P2P)}
Peer to peer model je často používanou alternativou pro tvorbu multiplayer her. Je nejčastěji používán u menších a arkádových titulů.\\

Pokud se bavíme o peer to peer komunikaci můžeme k ní přistupovat 2 způsoby. \textbf{Klient - Klient}, kdy si jsou klienti rovnocenní a \textbf{Host - Klient}, kdy jeden z klientů zároveň zastává roli serveru a poté pracuje podobně jako Server - Klient model.\\

První varianta Klient - Klient se v herním průmyslu téměř nepoužívá z důvodu hodnot spolehlivosti a udržení konzistence. V násladujícím textu budu mluvit pouze o Host - Klient modelu.\cite{unitynetworktopo}\cite{networktopo2}\\

\textbf{Výhody:}
\begin{itemize}
    \item Nenákladné: Model eliminuje potřebu centrálního serveru. Pro funkčnost hry nemusím jakožto tvůrce hry nic kontrolovat. Hráči si komunikaci zprostředkovávají sami. Proto je toto řešení velmi populární u \textit{indie} her.
\end{itemize}

\textbf{Nevýhody:}
\begin{itemize}
    \item Bezpečnostní rizika: Vzhledem k absenci přístupu ke komunikaci hráčů ztrácíte jako tvůrce hry autoritu nad komunikací.
    \item Výhoda hostícího klienta: Hostícímu klientovi jde jen stěží zabránit možnost podvádění, vzhledem k faktu, že server běří přímo na jeho zařízení. Výhodou hostícího klienta je i nulová latence z jeho strany. To tomuto  klientovi dává nadměrnou výhodu nad ostatními klienty.
\end{itemize}

\section{Nutnost autority serveru}

Pokud se bavíme o multiplayer hrách, často zmiňovaným tématem je podvádění hráčů. Pokud se hráč rozhodne podvádět, tak na úkor jeho komfortu silně zhoršuje zážitek ostatních hráčů. Naším cílem je možnostem podvádění zamezit. To není ale tak snadný úkol právě proto, že potřebujeme zachovat responzivitu hry a zároveň pracovat s latencí. Více o problematice latence v navázání na tuto kapitolu je rozepsáno v kapitole \textit{Problematika latence v multiplayer hrách} \ref{latency}.\\

Jedním ze základních a nejvíce účinných principů je zachování autority serveru. Autorita serveru má kromě anticheat výhod i výhodu v zachování kontinuity herní relace. To znamená, že 1 instance hry, právě ta na serveru, určuje správný stav hry a ostatní instance slouží jako loutky pro zobrazení dění na serveru. To také zamezuje vytváření situačních konfliktů.\\

V tomto modelu klient zastává takzvané funkce "hloupého klienta". Hloupý klient nemá autoritu a celkově správným principem je tomuto klientovi něvěřit. To znamená také omezit jeho vstupy pouze na ty, ke kterým musí mít oprávnění. Vezmeme ku příkladu pohyb hráče. Špatným přístupem by bylo povolit klientovi pohyb stylem, kdy klient zadá vstup k pohybu, ten se zpracuje lokálně a nakonec přemístění vyvolá zavoláním serveru "přemísti mne na souřadnici [22, 23]". Toto klientovi otevírá endpoint pro přemísťování bez omezení, a tím umožňuje jednoduché zfalšování vstupu. Náhle zkušený cheater má ve hře schopnost teleportace. Lepším přístupem je místo zpracování vstupu na straně klienta vstupní hodnotu přeposlat na server. Příkladem je upravená zpráva "Hráč se pohnul vpřed o vzdálenost 1". Samotný pohyb se poté zpracuje až na serveru. Samozřejmě toto také plně neřeší možnost zfalšování vstupu, ale již to vytváří překážky, se kterými se potencionální cheater musí vypořádat. Zároveň se tento přístup také jednodušeji zaobalí do dalších kontrolních vrstev, které detekují nesprávné chování klienta. Příkladem těchto vrstev může být limitování počtu vstupu v rámci herního ticku.\\

Praktikou je přeposílat hráčské vstupy a samotné zpracování těchto vstupů konat až na serveru, nikoliv u klienta.\\
\\
\textbf{Porušení autority serveru}\\

Mohou však nastat situace, které nemají jednoduché řešení pro autoritu serveru. V tyto výjimečné situace je promíjející převést autoritu na stranu klienta. Jakožto pro vývojáře je však důležité vědět, kdy si toto narušení může dovolit.\\

Jedním z nejznámějších výskytů autority klienta je střelba na protihráče. Pokud jakožto klient vystřelím kulku vůči nepříteli a mám zaměřovač přímo na jeho hlavě, očekávám, že protihráče zasáhnu. Problémem nastává fakt, že v tento moment já v mé lokální projekci světa vidím pozici protihráče opožděně vůči reálnému stavu na serveru. Pokud bych v tento moment vystřelil na serveru, hráče nemusím zasáhnout. Nevýhodou je, že pokud nyní umožníme klientovi zaslat zprávu "Zasáhl jsem hráče X a ubírám mu N životů." otevře se další vstup pro cheatery k zneužití. Autorita klienta se nedá plně ochránit proti cheatům, cheatování se ale dá ztížit způsobem implementace, která se hůře falšuje. Takovým řešením v tomto případě může být místo poslání přímé reference na hráče, který byl zasažen, poslat aktuální pozici střílejícího hráče, poté poslat pozici zasaženého hráče a náledně vykonat střelbu na serveru v rámci simulace kdy kontrolujeme jestli by opravdu střelba byla schopná protihráče zasáhnout a jestli je pro hráče reálné se v těchto pozicích vyskytovat. Nyní již místo zprávy "Zasáhl jsem X hráče". posílám zprávu "střílím jakožto X hráč z Y pozice na protihráče v Z pozici". Tento přístup stále má chyby, ale vytváření cheatů je náhle několikanásobně náročnější a většinu potencionálních cheaterů od vytváření cheatů odradí.
\cite{gambarch}

\section{Problematika latence v multiplayer hrách} \label{latency}
Hry pro více hráčů, které operují přes internet, musejí řešit nepříznivé problémy spjaté se síťovou komunikací. Jsou to problémy se kterými se, v porovnání k hrám pro jednoho hráče nebo lokálním multiplayer hrám, nesejdeme. Největším z těchto problémů je latence (lag). Latence je veličina popisující zpoždění mezi provedením akce a zobrazením očekávaného výsledku. Čím vyšší je latence, tím je hra více nehratelnou.\cite{unitylatency}\cite{cpredsrec}\\

Latence se stává obvzlášť problémem, když potřebujeme jako klient vykonat akci na serveru. V ten moment my zadáme příkaz, on se přepošle na server, tam se provede a poté je výsledek poslán zpátky na klienta. Tato akce však není instantní a vytváří se prodleva, než se  výsledek vrátí. Jako hráč však chci v rámci responzivity dostat výsledek ihned. Pokud ho neobdržím, bude pro mne zážitek z hry neintuitivní.\\

Latence se nedá eliminovat, dá se s ní však pracovat. Existují určité praktiky, které se používají k přelstění hráče. Cílem je zároveň přelstít hráče vytvořením iluze responzivity a k tomu zachovat autoritu serveru.\\

\subsection{Client prediction} \label{prediction}

Jak již z anglického názvu vyplývá, praktika client prediction slouží na bázi předpovídání klienta jakým způsobem se vstup, co bude zaslán na server, zachová. Znázornění, jakým způsobem toto předpovídání funguje v praxi, je v následující sekci znázorněno na pohybu hráče.
\begin{enumerate}
    \item Hráč zadá vstup "Jdi vpřed o vzdálenost 1."\space zmáčknutím klávesy pro chůzi vpřed. \textbf{Hráč je na pozici [20, 23] v čase 10.}
    \item Na server je zaslán RPC (remote procedure call) "Jdi vpřed o vzdálenost 1.", v tento moment se také vstup propočítá lokálně u zadávajícího klienta. Výsledná pozice tohoto zpracování se zapíše lokálně společně s aktuálním tickem (hodnotou herního času). \textbf{Hráč je na pozici [21, 23] v čase 11, pozice zapsána.}
    \item Na serveru je RPC obdržen, hráč je posunut. Zpět na klienta je zaslán výsledek zpracování s původní tick hodnotou. \textbf{Hráč byl posunut na pozici [21, 23] v čase 11.}
    \item Klient obdržuje výsledek zpracování a ten je porovnán s předpovězenou hodnotou. Pokud se hodnoty neshodují, hráč je přemístěn na pozici zadanou serverem. \textbf{Hodnoty [21, 23] a [21, 23] se shodují, předpovědění bylo úspěšné, přemístění se nekoná.}
\end{enumerate}

Tím ale samotný proces nekončí. V momentu, co se dostaví zpracovaná hodnota ze serveru, klient již s vysokou pravděpodobností zaslal nespočet dalších vstupů, které již také byly poslány na server pro ověřění. Toto zpracování popisuje praktika \textit{Server reconciliation} \ref{reconciliation} a bez této praktiky client prediction nemůže fungovat.\cite{unitylatency}\cite{cpredsrec}

\subsection{Server reconciliation} \label{reconciliation}

Tato praktika funguje ruku v ruce s praktikou \textit{Client prediction} \ref{prediction}, a tak i zároveň tato kapitola navazuje na zmíněnou kapitolu.\\

V moment, kdy obdržíme od serveru zprávu se zpracovanou pozicí a tato pozice se neshoduje s naší předpovězenou, by měl být hráč přemístěn na pozici zpracovanou. Toto přemístění nemůže být vykonáno jen tak. Klient s nejvyšší pravděpodobností již zpracoval nespočet jiných vstupů, a tak by jeho aktuální předpovězená pozice ztratila všechny vstupy, které byly zadané po této nesprávné predikci.\cite{unitylatency}\cite{cpredsrec}\\

Způsob řešení tohoto problému jaký zastává tato praktika je následný. Po zmíněné akci upravení a přesunutí na správnou pozici je využito zapsaných vstupů z minulosti. Vstupů zadaných po vstupu špatně předpovězeném. Tyto vstupy jsou znovu provedeny, tentokrát již však z nově upravené pozice, a jejich hodnoty výsledků jsou aktualizovány. Tento postup je znázorněn na nadcházející ukázce.
\begin{enumerate}
    \item Klient obdržuje ze serveru odpověď, že pozice zpracovaného vstupu v čase 12 je [22, 23]. Klient nachází lokální záznam pozice z času 12. Tím je [23, 23]. Hodnoty se neshodují a tak dochází na přepisování.
    \item Objekt je přemístěn na správnou serverovou pozici. Tím začíná proces rekonciliace. \textbf{Aktuální lokální pozice je změněna na [22, 23].}
    \item Klient vybírá všechny vstupy zadané po čase 12. Za každý zápis vstup zprocesovává a přepisuje původní hodnotu stavu objektu v daném čase novým stavem po zprocesování. Tento úkon se provádí, dokud nejsou všechny vstupy znovu zpracovány. \textbf{Mezi dalšími vstupy bylo 3x posunutí vpřed, aktuální zobrazovaná pozice u klienta tedy je [22 + 3, 23] = [25, 23] a všechny mezifáze jsou zapsány odpovědně.}
\end{enumerate}

Vlastní implementaci těchto praktik v rámci tohoto projektu popisuji v diagramu aktivit \ref{fig:networkplayercontroller} v kapitole \textit{Pohyb hráče} \ref{playermovement}.\cite{unitylatency}\cite{cpredsrec}



\chapter{Jak funguje hra}

Cílem projektu bylo vytvořit hru pro více hráčů s propojením hráčů skrze internetovou síť. Hra spočívá v tom, že se hráč objeví v aréně a jeho cílem je zůstat poslední naživu. Kola se opakují, dokud jeden z hráčů není úplným vítězem. Mezi koly dostává hráč možnost vylepšovat svoje vybavení užitím rougelike prvků. Čím je toto řešení originální od odstatních podobných her je fakt, že hlavní zbraní se stává klacek, který si hráči musejí sami nalézt a následně vylepšovat.

\section{Hráčské vstupy}

\begin{tabular}{|c|c|}
    \hline
    Vstup & Funkce \\
    \hline
    W & Chůze vpřed \\
    A & Chůze vlevo \\
    S & Chůze vzad \\
    D & Chůze vpravo \\
    Mezerník & Skok \\
    E & Sebrání itemu \\
    Q & Zahození itemu \\
    Levé tlačítko myši & Střelba \\
    \hline
\end{tabular}

\section{Průběh hry}

\textbf{Začátek hry}

Na začátku hry se připojení hráči objeví v aréně bez jakéhokoliv vybavení. V tento moment začíná odpočet. Dokud neskončí odpočet, hráč nemůže opustit svoji pozici. Hráč má čas pro zmapování prostředí a zamyšlení se nad strategií pro začátek kola.

Po uplynutém odpočtu souboj začíná a hráč je propuštěn. Cílem kola je nalézt nejlepší funkční zbraň (klacek), tím získat výhodu do dalších kol a zůstat jakožto poslední živý hráč.

V momentě, kdy je pouze 1 hráč naživu, je mu navýšen počet vyhraných kol o 1 (hráč potřebuje 3 vyhraná kola pro celkové vítězství ve hře) a kolo se ukončuje. Hráči se přemísťují do vylepšovacího kola.
\\\\
\textbf{Vylepšovací kolo}

Vylepšovací kolo začíná výběrem ze 3 karet vylepšení.

Po výběru jsou hráčům představeny jejich inventářé s vlastněnými vylepšeními zbraně (klacku). Zde se jim zobrazuje zbraň (klacek), kterou našli v prvním kole (pokud žádnou zbraň (klacek) nenalezli, je jim přidělena nejzákladnější varianta zbraně (klacku)). Hráč v této fázi upravuje svoji zbraň (klacek) přetahováním nově získaných vylepšení na zbraň (klacek).

Po odsouhlasení všech hráčů k postupu do dalšího kola jsou hráči opět přesměrováni do arény a začíná běžné soubojové kolo.
\\\\
\textbf{Běžné soubojové kolo}

Probíhá stejně jako první kolo hry. Rozdílem je, že se nyní již po mapě neobjevují sbíratelné zbraně (klacky). Hráč se totiž objeví již vybaven zbraní (klackem) z jeho inventáře.
\\\\
\textbf{Konec hry}

Hra končí, když jeden z hráčů dosáhne 3 vyhraných kol.

\section{Princip fungování klacku}

Hlavní zbraní hry je klacek. Každý hráč může mít právě 1 zbraň (klacek). Vlastnosti zbraně (klacku) následně může upravovat pomocí vylepšení, která získává mezi soubojovými koly hry.

\subsection{Střelný tok klacku}

Střelný tok zbraně (klacku) je veličina vytvořená pro zjednodušení abstraktního popisu fungování zbraně (klacku) při aplikování vylepšení.

\subsection{Vylepšení klacku}

Vylepšení zbraně (klacku) se dělí na 2 typy:

\begin{itemize}
    \item \textbf{Rozdělovače}: Funkcí rozdělovačů je dělit (větvit) střelný tok zbraně (klacku) z jednoho na dva nebo více dalších. Rozdělovače nijak neupravují hodnotu střelného toku zbraně (klacku).
    \item \textbf{Vylepšovače}: Funkcí vylepšovačů je upravit hodnotu střelného toku zbraně (klacku). Vylepšovače nijak nedělí (nevětví) střelný tok zbraně (klacku).
\end{itemize}

\subsection{Seznam obsažených vylepšení}

\begin{itemize}
    \item \textbf{Ohnivé vylepšení}
    \item \textbf{4-fázové nabíjecí vylepšení}
    \item \textbf{Šiškové vylepšení}
    \item \textbf{Dvojrozdělovač}
\end{itemize}

\subsection{Seznam typů hlavňové střelby a jak jich dosáhnout}

\begin{itemize}
    \item \textbf{Kulka}: Střela, které ihned zasahuje zaměřený cíl, základní forma střelby (\textit{žádné vylepšení})
    \item \textbf{Zápalná kulka}: Střela, která při zasažení zapálí zasaženého hráče (\textit{ohnivé vylepšení})
    \item \textbf{Šišky}: Projektil, ubírá život při přímém zásahu (\textit{šiškové vylepšení})
    \item \textbf{Výbušné šišky}: Projektil, při kolizi vybuchuje (\textit{šiškové vylepšení + zápalné vylepšení})
\end{itemize}

Projektil = střela, která letí pomalu a má spád

\chapter{Implementace}

V této části popisuji jednotlivé herní mechaniky a systémy do detailu, ne pro běžného hráče. Projekt byl vytvářen v herním enginu Unity, proto se v následující části vyskytují výrazy a pojmy specifické pro toto vývojové prostředí.

\section{Použité nástroje a služby}

Unity Engine, C\#, Unity Netcode, Unity Relay

\section{Struktura}

Projekt se pohybuje v rozsahu 5 scén.\\

\begin{figure}[h]
    \centering
    \includegraphics[width=\linewidth]{images/diagrams/scenes.png}
    \caption{Scenes}
    \label{fig:scenes}
\end{figure}

První scénou je scéna \textbf{Menu}. Ta slouží jako hlavní a první scéna, se kterou se hráč setká. Zde si hráč volí, zda-li chce server hostovat, nebo se k serveru připojit. Po zvolení volby je vytvořený NetworkManager viz diagram \ref{fig:scenesandmanagers}. Při hostování se vytvoří server a relay alokace zavoláním UnityRelay api. Při volbě join je klient napojen na relay alokaci skrze kód získaný od hostujícího klienta. Pokud jakákoliv akce selže, klient je vrácen zpět do menu. Pokud je vše vykonáno úspěšně, klient je přesměrován na scénu MultiplayerLobby.\\

\begin{figure}
    \centering
    \includegraphics[width=1\linewidth]{images//diagrams/acMenu.png}
    \caption{Diagram aktivit procesu hostování/ napojení se na server}
    \label{fig:enter-label}
\end{figure}

Ostatní scény spadají do sekce multiplayer scén, které nefungují, pokud nejsou načteny v rámci správného napojení na server a není provedena validní alokace skrze Unity Relay.\\

Druhou scénou je scéna \textbf{MultiplayerLobby}. Tato scéna slouží pro umožnění ostatním hráčům se připojit do session před započetím hry. Za každého připojeného hráče je vytvořena právě 1 instance PlayerManageru, která zůstává po celou dobu existence objektu NetworkManager. Po splnění všech souhlasů se započetím hry v ReadyButton komponentě (využívá \hyperref[networksuccessbutton]{NetworkSuccessBtn}) host vyvolá u všech klientů přesměrování na scénu CombatRound. Tím se spouští hra a je vytvořená komponenta GameManager, která  spravuje chod průběhu hry. Opět vyobrazeno v diagramu \ref{fig:scenesandmanagers}. Na stejné úrovni také pracuje vrstva UpgradeManager a PlayerGunManager pod každou 1 instancí PlayerManageru.\\

Třetí scénou je scéna \textbf{CombatRound}. Scéna slouží k souboji hráčů. Na začátku je za každý PlayerManager \hyperref[dic:instancovat]{instancován} a \hyperref[dic:spawn]{spawnut} právě jeden \hyperref[playerobject]{PlayerObject}, který řeší jednotlivé hráčské mechaniky v rozsahu 1 hráčského kola. O samotném hráčském objektu a jeho nespočtu funkcí se dočtete více v kapitole \ref{playerobject} Postava hráče. Po dokončení herního kola je rozpoznáno, zda-li některý z hráčů je ve vítězné pozici. Pokud ano, jsou klienti hostem přesměrováni do scény WinerScene, pokud tomu tak není, jsou přemístěni do scény UpgradeRound.\\

Čtvrtou scénou je scéna \textbf{UpgradeRound}. Scéna slouží k úpravě a aplikování vlastněných vylepšení zbraně (klacku). Scéna operuje ve 2 fázích. V první fázi si klient vybírá nové vylepšení zbraně (klacku). V druhé fázi již probíhá zmíněná úprava. Po odsouhlasení všech hráčů o připravenosti jsou klienti přemístěni zpět do CombatRound scény.\\

Pátou scénou je scéna \textbf{WinnerScene}. Tato scéna slouží pro zobrazení vítězného žebříčku po skončení hry.\\

\begin{figure}[h]
    \centering
    \includegraphics[width=\linewidth]{images/diagrams/gameArchitecture.png}
    \caption{Scenes and managers}
    \label{fig:scenesandmanagers}
\end{figure}

Jednotlivé funkce z pohledu uživatele jsou popsány v UseCase diagramu viz. příloha \ref{fig:usecaseplayer} a \ref{fig:usecasesession}.

\begin{figure}[h]
    \centering
    \includegraphics[width=0.5\linewidth]{images//diagrams/useCasePlayer.png}
    \caption{UseCase základní diagram}
    \label{fig:usecaseplayer}
\end{figure}

\begin{figure}[h]
    \centering
    \includegraphics[width=\linewidth]{images//diagrams/useCaseSession.png}
    \caption{UseCase diagram v rámci herní session}
    \label{fig:usecasesession}
\end{figure}

\pagebreak

\section{Manažer hráče - PlayerManager} \label{playermanager}
Vytváří se s každým připojeným klientem. Ovládá a odkazuje se na objekty a data spjaté se zastupujícím klientem.\\
Obsahuje 3 spravující třídy:
\begin{itemize}
    \item PlayerManager
    \item UpgradeManager
    \item PlayerGunManager
\end{itemize}

\subsection{Třída PlayerManager} \label{playermanagerclass}
\textbf{Dědí z třídy:} \href{https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@1.8/api/Unity.Netcode.NetworkBehaviour.html}{NetworkBehaviour}\cite{unity-netcode}\\
\textbf{Účel:} Slouží jakožto správce klienta, vytváří a ničí hráčský objekt.\\
\\
\textbf{Veřejné proměnné:}\\
\begin{tabular} {|l|l|p{50mm}|}
\hline
Název proměnné & datový typ & funkce\\
\hline
\hline
PlayerName & \href{https://docs-multiplayer.unity3d.com/netcode/1.0.0/basics/networkvariable/}{NetworkVariable}\cite{unity-netcode-networkvariable}\textless FixedString32Bytes\textgreater & Drží hodnotu jména hráče.\\
\hline
PlayerObject & \hyperref[playerclass]{Player} & Odkazuje na třídu v instanci \hyperref[playerobject]{hráčského objektu}.\\
\hline
\end{tabular}
\\
\\
\textbf{Veřejné metody:}\\
\begin{tabular} {|l|p{60mm}|p{50mm}|}
\hline
Název metody & argumenty & funkce\\
\hline
\hline
SpawnPlayerObject & Vector3 spawnPosition\newline Quaternion rotation = new()\newline bool areControlsDisabled = true\newline bool withCamera = true & \hyperref[dic:instancovat]{Instancuje} a \hyperref[dic:spawn]{spawne} hráčský objekt.\\
\hline
DespawnPlayerObject & -- & Zničí hráčský objekt napříč všechna připojení.\\
\hline
\end{tabular}
\\


\section{Herní objekt hráče - PlayerObject} \label{playerobject}
Herní objekt hráče je nejkomplexnějším objektem celého projektu. Obsahuje 7 sobě specifických tříd, které přidávají vrsty funkcí a navzájem se doplňují.\\
\\
\textbf{Struktura objektu:}

\dirtree{%
.1 PlayerObject.
.2 NameTag -- ukazatel jména hráče.
.2 Head.
.3 Face -- cílový objekt pro rig \href{https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.1/manual/constraints/TwoBoneIKConstraint.html}{Two Bone IK Contraint}.
.3 ThirdPersonCamera.
.2 Hand -- objekt slouží jako placeholder pro vybavený item.
.3 HandRigHold -- cílový objekt pro rig \href{https://docs.unity3d.com/Packages/com.unity.animation.rigging@1.1/manual/constraints/MultiAimConstraint.html}{Multi-Aim Contraint}.
.2 PlayerModel -- obsahuje model hráče a jeho rig.
.2 DownCollisionLimit -- určuje vzdálenost hranice kolize směrem dolů.
.2 FwdCollisionLimit -- určuje šířku hranic kolize směrem do stran.
}
\vspace{10mm}
\noindent \textbf{Struktura objektu s komponenty:}

\dirtree{%
.1 PlayerObject.
.3 \color{gray} Capsule Collider.
.3 \color{gray} Rigidbody.
.3 \color{gray} Network Object.
.3 \color{gray} script Player.
.3 \color{gray} script NetworkPlayerController.
.3 \color{gray} script PlayerInventory.
.3 \color{gray} script PlayerHealth.
.3 \color{gray} script PlayerShoot.
.3 \color{gray} script PlayerCamera.
.3 \color{gray} script LocalPlayer.
.2 NameTag.
.2 Head.
.3 Face.
.3 ThirdPersonCamera.
.2 Hand.
.4 \color{gray} Network Object.
.3 HandRigHold.
.2 PlayerModel.
.3 \color{gray} Animator.
.3 \color{gray} Rig Builder.
.4 \color{gray} ...rig Constraints.
.2 DownCollisionLimit.
.2 FwdCollisionLimit.
}
\vspace{10mm}
\noindent \textbf{Jak je to s kolizemi?}

Jak lze ze struktury poznat, hráčský objekt řeší kolize dvěma způsoby. Proč? Protože pro rigidbody vlastnosti využívá systém fyziky poskytnutý od Unity, ale tento systém není dostatečně spolehlivý v rámci předpovídatelnosti pohybu hráče mezi zařízeními. Proto samotný vstup od hráče propisuje skrze vlastní implementaci kontroly kolizí. Více k zpracování pohybu v kapitole \ref{playermovement} Pohyb Hráče.

\subsection{Třída Player} \label{playerclass}
\textbf{Dědí z třídy:} \href{https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@1.8/api/Unity.Netcode.NetworkBehaviour.html}{NetworkBehaviour}\cite{unity-netcode}\\
\textbf{Účel:} Slouží jako základní třída hráčského objektu a řeší například jeho inicializaci, či ovládá funkčnost jiných systémů postavy.
%OPTIONAL TODO
\subsection{Třída PlayerInventroy} \label{playerinventoryclass}
\textbf{Dědí z třídy:} \href{https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@1.8/api/Unity.Netcode.NetworkBehaviour.html}{NetworkBehaviour}\cite{unity-netcode}\\
\textbf{Účel:} Zařizuje správnou funkci pro sbírání a odhazování itemů.
%OPTIONAL TODO
\subsection{Třída PlayerHealth} \label{playerhealthclass}
\textbf{Dědí z třídy:} \href{https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@1.8/api/Unity.Netcode.NetworkBehaviour.html}{NetworkBehaviour}\cite{unity-netcode}\\
\textbf{Účel:} Spravuje systém zdraví hráčského objektu.\\
\\
\textbf{Veřejné proměnné:}\\
\begin{tabular} {|l|l|p{80mm}|}
\hline
Název & Datový typ & Popis\\
\hline
Health & NetworkVariable\textless int\textgreater & Reprezentuje hodnotu počtu životů. Pokud je tato hodnota na nule setter nastaví instanci hráče na mrtvého.\\
\hline
\end{tabular}
\\
\\
\\
\textbf{Veřejné metody:}\\
\begin{tabular} {|l|l|p{80mm}|}
\hline
Název & Argumenty & Popis\\
\hline
Damage & int amount & Odebere hodnotu z počtu životů.\\
\hline
Heal & int amount & Přidá hodnotu k počtu životů. Limituje celek na maximální hodnotu 100.\\
\hline
\end{tabular}
%OPTIONAL TODO
\subsection{Třída PlayerCamera} \label{playershootclass}
\textbf{Dědí z třídy:} \href{https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@1.8/api/Unity.Netcode.NetworkBehaviour.html}{NetworkBehaviour}\cite{unity-netcode}\\
\textbf{Účel:} Vytváří a spravuje instanci hráčské kamery a služby spojené s ní.
%OPTIONAL TODO
\subsection{Třída PlayerShoot} \label{playershootclass}
\textbf{Dědí z třídy:} \href{https://docs.unity3d.com/ScriptReference/MonoBehaviour.html}{MonoBehaviour}\\
\textbf{Účel:} Pokud je hráč lokální, zaznamenává vstup pro střelbu od uživatele a spouští veřejnou akci ShootInput.\\
\\
\textbf{Veřejné proměnné:}\\
\begin{tabular} {|l|l|p{80mm}|}
\hline
Název & Datový typ & Popis\\
\hline
ShootInput & Action\textless bool\textgreater & Vyvolá se, když hráč vyvolává vstup střelby. Bool hodnota udává zda-li se jedná o započetí stisknutí vstupu a nebo je vstup stisknutý déle (užitečné například pro určení semi-automatická vs automatická střelba).\\
\hline
\end{tabular}

\subsection{Třída LocalPlayer} \label{localplayerclass}
\textbf{Dědí z třídy:} \href{https://docs.unity3d.com/ScriptReference/MonoBehaviour.html}{MonoBehaviour}\\
\textbf{Účel:} Je aktivní pouze pokud je postava lokálním hráčským objektem. Je určena k lokálně specifickým funkcím.\\

\subsection{Pohyb hráče} \label{playermovement}

K pohybu hráče slouží třída NetworkPlayerController, která zajišťuje synchronizaci pohybu skrze připojené klienty. Třídá obsahuje také samotnou funkci pro zpracování pohybu dle vstupů, nazývá se HandleMovement, která je více popsána v kapitole \ref{handlemovement}.

Pohyb hráče je třeba synchronizovat mezi serverem a klientem. To na serveru není problém, u klienta nám ale vznikají komplikace. Cílem je dosáhnout responzivnosti na straně klienta, ale zároveň dodržet autoritu serveru. V implementaci aplikuji praktiky předpovídajícího klienta a serverové rekonciliace. Proč a jakým způsobem tyto praktiky fungují, popisuji v kapitolách \ref{prediction} a \ref{reconciliation}. Samotná implementace v tomto projektu je rozšířena navíc o seskupování více vstupů v rámci jednoho herního ticku za účelem snížení frekventovanosti posílání packetů dat mezi klientem a serverem.

Celý postup za zpracováním pohybu je popsán v diagramu aktivit \ref{fig:networkplayercontroller}.

\begin{figure}
    \centering
    \includegraphics[width=1\linewidth]{images/diagrams/networkPlayerController.png}
    \caption{Diagram aktivit - NetworkPlayerController}
    \label{fig:networkplayercontroller}
\end{figure}

\subsubsection{Metoda HandleMovement} \label{handlemovement}

\textbf{Parametry:}\\
\begin{tabular} {|l|l|}
\hline
typ & název \\
\hline
\hline
Vector3 & movementInput\\
\hline
Vector3 & rotationInput\\
\hline
float & deltaMultiplier\\
\hline
\end{tabular}
\\

\noindent \textbf{Zpracování pohybového vstupu}

Pro optimalizaci je vykonáváno, pouze pokud není \texttt{movementInput} hodnota nulovým vektorem.

\begin{enumerate}
    \item Nejdříve vypočítáme hodnotu pohybového vektoru vynásobením \texttt{movementInput} s \texttt{deltaMultiplier} (s hodnotou se pracuje jako s lokální hodnotou vůči hráčskému objektu).
    \item Vypočteme offsetový vektor se směrem pohybového vektoru s absolutní velikostí dle nastaveného poloměru šířky kolize herní postavy.
    \item Přidáme offsetový vektor k pohybovému vektoru.
    \item Vyšleme raycast ze středu hráčského objektu ve směru pohybového vektoru s jeho absolutní velikostí. Pokud dojde ke kolizi, snížíme velikost pohybového vektoru na velikost dle vzdálenosti zásahu.
    \item Tím úspěšně získáváme reálnou možnou vzdálenost pohybu hráče vůči kolizím (stále s přidaným offsetem dle šířky hráče).
    \item Následně z nové pozice vyšleme raycast směrem dolů v určené vzdálenosti dle bodu dolní podstavy hráče pro nastavení správného umístění hráčské postavy ve výšce. Pokud dochází ke kolizi, posuneme cílový pohybový vektor o chybějící výškový rozdíl nahoru.
    \item Poté odečteme offsetový vektor od pohybového vektoru a skrze funkci \textit{transform.Translate} posuneme postavu hráče na novou pozici.
    \item Na úplný konec zkontrolujeme, jestli není pohyb hráče až moc vysoký. Pokud ano, tak pohybovou akci zrušíme. Kontrola je prováděna porovnáním, zda-li dvojitá vzdálenost posunutí nahoru je větší než-li vzdálenost pohybu do strany.
    \[ 0.5 * vzdálenost\ nahoru > vzdálenost\ do\ strany \]
    \[ 0.5y > \sqrt{x^2 + z^2} \]
    Vizualizováno v grafu zjednodušeného průřezu \ref{fig:2dmovementview} a v trojrozměrném grafu \ref{fig:movementview}.
\end{enumerate}

\begin{figure}[h]
    \centering
    \begin{tikzpicture}
    \begin{axis}
    \addplot[color=red, domain=-1:1]{abs(x)*2};
    \end{axis}
    \end{tikzpicture}
    \caption{Průřez vizualizace omezení pohybu}
    \label{fig:2dmovementview}
\end{figure}

\begin{figure}[h]
    \centering
%\begin{tikzpicture}
%\begin{axis}[
%    colormap/cool,
%]
%\addplot3[
%    surf,
%    samples=30,
%    domain=-1:1,
%    opacity=0.5,
%]
%{sqrt(x^2+y^2)*2};
%\end{axis}
%\end{tikzpicture}
    \includegraphics[width=0.5\linewidth]{images/other/movementGraph.png}
    \caption{Vizualizace omezení pohybu}
    \label{fig:movementview}
\end{figure}

\noindent \textbf{Zpracování rotačního vstupu}

Pro optimalizaci je vykonáváno, pouze pokud není \texttt{rotationInput} hodnota nulovým vektorem.

\begin{enumerate}
    \item Otočíme celý hráčský objekt o hodnotu X vynásobenou \texttt{deltaMultiplier} kolem osy X. Rozsah je omezen na -90° až 90°.
    \item Otočíme hlavu a ruku hráčského objektu o hodnotu Y vynásobenou \texttt{deltaMultiplier} kolem osy Y.
\end{enumerate}

\subsubsection{Struct TransformState}

TransformState je struktura, která nám slouží k zapsání aktuální pozice hráče. Je přizpůsobená pro rozhraní \href{https://docs-multiplayer.unity3d.com/netcode/current/advanced-topics/serialization/inetworkserializable/}{INetworkSerializable}\cite{unity-netcode-serialization}.
\\
\textbf{Hodnoty:}\\
\begin{tabular} {|l|l|l|}
\hline
Typ & Název & Popis\\
\hline
\hline
public int & Tick & Zapisuje kdy udaný stav nastává.\\
\hline
public Vector3 & Position & Celková pozice objektu hráčské postavy.\\
\hline
public Quaternion & Rotation & Celková rotace objektu hráčské postavy.\\
\hline
public Quaternion & Facing & Rotace pohledu hráčské postavy (může se lišit od celkové rotace).\\
\hline
\end{tabular}
\\

\section{Stavba klacku}

Zbraň (klacek) se skládá ze 3 typů komponent:

\begin{center}
    \begin{tabular}{|l|l|p{80mm}|}
         \hline
         Název & C\# třída & Popis \\
         \hline
         \hline
         Zdroj klacku & \hyperref[gbase]{GBase} & Vytváří střelný tok. Má 1 ukončení na které lze umístít \textbf{vylepšení}, či \textbf{hlaveň}.\\
         \hline
         Vylepšení klacku & \hyperref[gupgrade]{GUpgrade} & Umisťuje se mezi \textbf{zdroj} a \textbf{hlaveň}. Upravuje střelný tok.\\
         \hline
         Hlaveň klacku & \hyperref[gmuzzle]{GMuzzle} & Generuje se na konci střelného toku. Při aktivaci vyvolá střelbu. Střelbu si musí definovat každý typ hlavně zvlášť.\\
         \hline
    \end{tabular}
\end{center}

Stavba zbraně (klacku) je implementována dvěma způsoby -- v lokálním prostředí a ve sdíleném prostředí (lokálním prostředím je například scéna vylepšování zbraně (klacku), kdy není potřeba, aby byl objekt rozpoznán mezi propojeními, a ve sdíleném je například scéna souboje, kdy ten samý objekt je potřeba zobrazovat synchronizovaně u více hráčů najednou).

\subsection{Herní objekt zdroje - GBase}

\label{gbase}

\textbf{Struktura objektu:}

\dirtree{%
.1 GBase.
.2 \hyperref[point]{Point} -- určuje místo pro umístění child komponenty.
.2 Model.
}

\noindent \textbf{Využití objektu}\\
Objekt využíváme v případě generace zbraně jako zdrojovou, rodičovskou komponentu. Následně nám zprostředkovává funkce pro ovládání samotné fuknčnosti zbraně.


\begin{center}
    \begin{center}
    \textit{Tento objekt \to}
    \begin{tabular}{c}
        \hyperref[gmuzzle]{Gmuzzle}\\
        \hline
        \hyperref[gupgrade]{GUpgrade}
    \end{tabular}
    \end{center}
\end{center}

\subsection{Herní objekt vylepšení - GUpgrade}
\label{gupgrade}

\textbf{Struktura objektu:}

\dirtree{%
.1 GUpgrade.
.2 GPartStencil.
.3 DestinyPoints -- určuje místa pro umístění child komponent.
.4 ...\hyperref[point]{Point}s.
.3 Model.
}
\\
\noindent \textbf{Struktura objektu s komponenty:}

\dirtree{%
.1 GUpgrade.
.2 GPartStencil.
.4 \color{gray} class GUpgrade. 
.5 \color{gray} UpgradeId -- Id číslo pro Upgrade definované v třídě UpgradeManager.
.5 \color{gray} TotalOutline -- odkaz na Outline komponentu.
.5 \color{gray} PartOutline -- odkaz na Outline modelu komponentu.
.5 \color{gray} Destiny[] -- odkaz na DestinyPoints.
.3 DestinyPoints -- určuje místa pro umístění child komponent.
.4 ...\hyperref[point]{Point}s.
.3 Model.
}


\noindent \textbf{Využití objektu}\\
Objekt využíváme v případě generace zbraně jako navazující komponentu. Komponenta je umístěna na jakoukoliv \hyperref[point]{Point} komponentu spadající pod \hyperref[gbase]{GBase} nebo \hyperref[gupgrade]{GUpgrade}, následně přesměrována a upravuje volání funkcí z rodičovského objektu do child objektu (child objektem může být \hyperref[gmuzzle]{Gmuzzle} nebo 
\hyperref[gupgrade]{GUpgrade}).

\begin{center}
\begin{center}
\begin{tabular}{c}
    \hyperref[gbase]{GBase}\\
    \hline
    \hyperref[gupgrade]{GUpgrade}
\end{tabular}
\textit{
\to Tento objekt \to
}
\begin{tabular}{c}
    \hyperref[gmuzzle]{Gmuzzle}\\
    \hline
    \hyperref[gupgrade]{GUpgrade}
\end{tabular}
\end{center}
\end{center}

\subsection{Herní objekt hlavně - GMuzzle}
\label{gmuzzle}

\textbf{Struktura objektu:}

\dirtree{%
.1 GMuzzle.
.2 \hyperref[point]{Point} -- určuje místo pro umístění child komponenty.
.2 Model.
}


\begin{center}
\begin{tabular}{c}
    \hyperref[gbase]{GBase}\\
    \hline
    \hyperref[gupgrade]{GUpgrade}
\end{tabular}
\textit{
\to Tento objekt
}

\end{center}


\subsection{Herní objekt Point}
\label{point}

\textbf{Struktura objektu:}
\dirtree{%
.1 Point.
}

Slouží jako propojující bod mezi komponenty zbraně. Obsahuje odkaz na rodičovskou \hyperref[gbase]{GBase} nebo \hyperref[gupgrade]{GUpgrade} a odkaz na child objekt \hyperref[gmuzzle]{GMuzzle} nebo \hyperref[gupgrade]{GUpgrade}.\\

\subsection{Šablona herního objektu GPartStencil}
\dirtree{%
.1 GPartStencil.
.2 DestinyPoints -- určuje místa pro umístění child komponent.
.3 ...\hyperref[point]{Point}s.
.2 Model.
}

\subsection{Abstraktní třída GPart} \label{gpart}

\textbf{Dědí z třídy:} \href{https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@1.8/api/Unity.Netcode.NetworkBehaviour.html}{NetworkBehaviour}\cite{unity-netcode}\\
\textbf{Účel:} Slouží jakožto základ pro všechny třídy tvořící součásti zbraně (klacku).\\
\textbf{Dědí z ní třídy:}
\begin{itemize}
    \item \hyperref[gbase]{GBase}
    \item \hyperref[gupgrade]{GUpgrade}
    \item \hyperref[gmuzzle]{GMuzzle}
\end{itemize}
\\
\textbf{Metody:}\\
\begin{tabular} {|l|l|l|l|}
\hline
Název metody & typ & argumenty & funkce\\
\hline
\hline
\hypertarget{shootMethod}{Shoot} & abstract & ShootData shootData, Player owner & Tvorba střelného toku.\\
\hline
\end{tabular}

\subsection{Třída GBase} \label{gbase}

\textbf{Dědí z třídy:} \hyperref[gpart]{GPart}\\

\noindent \textbf{Veřejné metody:}\\
\begin{tabular} {|l|l|l|p{60mm}|}
\hline
Název metody & typ & argumenty & funkce\\
\hline
\hline
Shoot & \hyperlink{shootMethod}{override} & bool isFirstShot, Player owner & Zdrojovou funkcí střelného toku. Při vybavení do ruky hráče je její zavolání vázáno k vstupu střelby hráče.\\
\hline
\end{tabular}

\subsection{Abstraktní třída GUpgrade} \label{gupgrade}

\textbf{Dědí z třídy:} \hyperref[gpart]{GPart}\\
\textbf{Účel:} Slouží jakožto základ pro třídy vylepšení\\
\\
\textbf{Veřejné proměnné:}\\
\begin{tabular} {|l|l|l|}
\hline
Název & Datový typ & Popis\\
\hline
\hline
UpgradeId & ulong & ukládá Id vylepšení.\\
\hline
Destiny & GDestiny[] & zde se odkazují navazující vylepšení.\\
\hline
\end{tabular}
\\\\
\textbf{Veřejné metody:}\\
\begin{tabular} {|l|l|p{40mm}|p{60mm}|}
\hline
Název & Typ & Argumenty & Popis\\
\hline
\hline
Shoot & \hyperlink{shootMethod}{override} & ShootData shootData, Player owner & Upravuje vstupní hodnotu \textit{ShootData} a spouští ji u svých \textit{Destiny} komponent.\\
\hline
ReplacePart & - & UpgradeWithPart uwp, bool isNetwork & Vytvoří instanci zadaného vylepšení a nahradí ho za nastávající. IsNetwork učuje, jestli se jedná o lokální či síťové prostředí.\\
\hline
\end{tabular}\\

\subsection{Abstraktní třída GMuzzle} \label{gmuzzle}

\textbf{Dědí z třídy:} \hyperref[gpart]{GPart}\\
\textbf{Účel:} Slouží jakožto základ pro třídy hlavně\\
\\
\textbf{Veřejné proměnné:}\\
\begin{tabular} {|l|l|l|}
\hline
Název & Datový typ & Popis\\
\hline
--&--&--\\
\hline
\end{tabular}
\\\\
\textbf{Veřejné metody:}\\
\begin{tabular} {|l|l|l|p{60mm}|}
\hline
Název & Typ & Argumenty & Popis\\
\hline
\hline
Shoot & \hyperlink{shootMethod}{override} & ShootData shootData, Player owner & Přebírá vstupní \textit{ShootData} komponentu a definuje a vyvolává funkci střelby\\
\hline
\end{tabular}

\subsection{Ukládání klacku}

Na každou hráčskou postavu se váže 1 manažer zbraně (klacku) \textit{PlayerGunManager} \ref{playergunmanager} Ten má na sobě síťovou proměnnou (\href{https://docs-multiplayer.unity3d.com/netcode/1.0.0/basics/networkvariable/}{NetworkVariable}\cite{unity-netcode-networkvariable}) GunBaseSaveData sloužící k univerzální formě zapsání struktury zbraně (klacku) v grafové podobě. Obsahuje metody pro spawn zbraně (klacku) pro lokální použití, spawn zbraně (klacku) pro sdílené použití, zapsání struktury do textové podoby, přeložení z textové podoby do \textit{GunBaseSaveData} podoby.

\subsubsection{Třída GunBaseSaveData} \label{gbsd}

Třída GunBaseSaveData slouží k zapsání struktury zbraně (klacku) do grafové podoby. Je přizpůsobená pro rozhraní \href{https://docs-multiplayer.unity3d.com/netcode/current/advanced-topics/serialization/inetworkserializable/}{INetworkSerializable}\cite{unity-netcode-serialization}.

\noindent \textbf{Konstruktor:}\\
argument - GBase gbase
-- Převezme zdroj zbraně (klacku) \textit{GBase} a dle něj zapíše strukturu zbraně (klacku) do grafové podoby.

\vspace{20mm}

\textbf{Ukázka grafové podoby}

\dirtree{%
.1 Zdroj - je vždy stejný.
.2 1 - Id součástky(rozdvojovač).
.3 4 - Id součástky(zápalné vylepšení).
.2 3 - Id součástky(šiškové vylepšení).
}


\section{Systém vylepšení}

Systém vylepšení má 2 vrstvy
\begin{enumerate}
    \item Všechna vylepšení
    \item Vylepšení se součástkou
\end{enumerate}\\

Důvod tohoto řešení je prostý. Základním typem vylepšení je vylepšení, které nám pozměňuje některou vlastnost hráčské postavy. Může jí být například rychlost pohybu či síla výskoku. Po té tu máme vylepšení, které nám přímo nemění hráčské statistiky, ale přidávají nám součástku zbraně do inventáře. Takové vylepšení nazýváme "Vylepšení se součástkou" nebo také \textit{UpgradeWithPart}.\\

Jeden typ vylepšení se součástkou má v rámci implementace stejný postup přidání jakožto jiný typ vylepšení se součástkou, proto se nám vyplatí, v rámci znovupoužitelnosti kódu a jednoduššímu přidávání nových vylěpšení, použít vlastní abstraktní třídu.\\

Hlavní komponentou pro zapsání a správu všech vylepšení je UpgradeManager, zároveň je UpgradeManager využíván pro zapsání všech vlastněných vylepšení.

Poté je tu PlayerGunManager. V něm se zapisují jednotlivé vlastněné součástky vylepšení zbraně (klacku). Vlastněná vylepšení se nám zde zapisují v listu tříd GUpgradeData.

\subsection{Třída UpgradeManager}
\textbf{Účel:} Slouží jakožto manažer všech vylepšení.\\
\textbf{Privátní statické proměnné:}\\
\begin{tabular} {|r|r|p{100mm}|}
\hline
Název & datový typ & Popis\\
\hline
\hline
\_upgradeTypes & List\textless Upgrade\textgreater & Obsahuje instance od všech hráčských vylepšení.\\
\hline
\end{tabular}
\\
\\
Ukázka \textit{\_upgradeTypes} deklarace:
\begin{lstlisting}
private static List<Upgrade> _upgradeTypes = new() {
    new UpgradeG2Splitter((int)Upgrades.G2Splitter),
    new UpgradeGChargeEnhancer((int)Upgrades.GChargeEnhancer),
    new UpgradeGConeEnhancer((int)Upgrades.GConeEnhancer),
    new UpgradeGFireEnhancer((int)Upgrades.GFireEnhancer),
};
\end{lstlisting}
\\
\textbf{Veřejné statické metody:}
\\
\begin{tabular} {|l|l|p{60mm}|}
\hline
Název & Argumenty & Popis\\
\hline
\hline
GetUpgradeById & int id & Vrací instanci vylepšení podle id hodnoty z listu \textit{\_upgradeTypes}.\\
\hline
GetRandomUpgrade & - & Vrací náhodné vylepšení.\\
\hline
GetRandomSetOfNonrepeatingUpgrades & int amount & Vrátí pole neduplikátních vylepšení o velikosti \textit{amount}.\\
\hline
\end{tabular}

\subsection{Enum Upgrades}
\textbf{Účel:} Zde se definuje jaké vylepšení má jaké Id. Je veřejné a určené pro jednoduché flexibilní užití v jiných scriptech.

\begin{lstlisting}
public enum Upgrades
{
    G2Splitter = 1,
    GChargeEnhancer = 3,
    GConeEnhancer = 4,
    GFireEnhancer = 5,
    //...
}
\end{lstlisting}

\subsection{Abstraktní třída Upgrade} \label{upgrade}
\textbf{Účel:} Určuje základní funkce a proměnné pro kartu vylepšení.\\

\noindent \textbf{Veřejné proměnné:}\\
\begin{tabular} {|l|l|p{42mm}|p{50mm}|}
\hline
Název proměnné & Datový typ  & Popis\\
\hline
\hline
Id & int & Id hodnota vylepšení.\\
\hline
Name & string & Název vylepšení.\\
\hline
\end{tabular}
\\

\noindent \textbf{Veřejné metody:}\\
\begin{tabular} {|l|l|p{42mm}|p{50mm}|}
\hline
Název metody & Typ & Argumenty & Funkce\\
\hline
\hline
OnAdd & abstract & \hyperref[playermanagerclass]{PlayerManager} pm & Má definovat, jak se má zachovat při \textbf{přidání} vylepšení k hráči předanému v argumentu.\\
\hline
OnDelete & abstract & \hyperref[playermanagerclass]{PlayerManager} pm & Má definovat, jak se má zachovat při \textbf{odebrání} vylepšení od hráče předanému v argumentu.\\
\hline
InstantiateCard & -- & Action\textless int\textgreater onSelected, int optionIdx & Vytvoří kartu vylepšení, přidá na ni onClick akci dle předané akce z argumentů, do které předává index karty opotionIdx také z argumentů.\\
\hline
GetImageSprite & -- & -- & Vrací Sprite s obrázkem vylepšení.\\
\hline
GetIconSprite & -- & -- & Vrací Sprite s ikonou vylepšení.\\
\hline
\end{tabular}
\\

\subsection{Abstraktní třída UpgradeWithPart}
\textbf{Dědí z třídy:} \hyperref[upgrade]{Upgrade}\\
\textbf{Účel:} Rozšiřuje třídu \textit{Upgrade} o funkce spjaté se součástkou, kterou reprezentuje.\\

\noindent \textbf{Veřejné metody:}\\
\begin{tabular} {|l|l|l|p{50mm}|}
\hline
Název metody & Typ & Argumenty & Funkce\\
\hline
\hline
OnAdd & override & \hyperref[playermanagerclass]{PlayerManager} pm & Při vyvolání \textbf{přidá} dané vylepšení do PlayerGunManageru hráče.\\
\hline
OnDelete & override & \hyperref[playermanagerclass]{PlayerManager} pm & Při vyvolání \textbf{odebere} dané vylepšení z PlayerGunManageru hráče.\\
\hline
InstantiatePrefab & -- & -- & Instancuje a vrací \newline \hyperref[gupgrade]{herní objekt vylepšení}.\\
\hline
GetBranchCount & abstract & -- & Má vracet počet zakončení pro dané vylepšení.\\
\hline
\end{tabular}
\\

\subsection{Třída PlayerGunManager}\label{playergunmanager}
\textbf{Dědí z třídy:} \href{https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@1.8/api/Unity.Netcode.NetworkBehaviour.html}{NetworkBehaviour}\cite{unity-netcode}\\
\textbf{Účel:} Slouží jakožto manažer pro zbraň (klacek) hráče.\\

\noindent \textbf{Veřejné proměnné:}\\
\begin{tabular} {|l|l|p{46mm}|}
\hline
Název proměnné & Datový typ  & Popis\\
\hline
\hline
GunCurrentData & \href{https://docs-multiplayer.unity3d.com/netcode/1.0.0/basics/networkvariable/}{NetworkVariable}\cite{unity-netcode-networkvariable}\textless \hyperref[gbsd]{GunBaseSaveData}\textgreater  & Hodnota reprezentuje \newline aktuální zbraň se všemi \newline aplikovanými vylepšeními.\\
\hline
GUpgradeInv & IEnumerable\textless \hyperref[gupgradedata]{GUpgradeData}\textgreater & Pouze get přístup pro získání dat ohledně vlastněných a aplikovaných vylepšení.\\
\hline
\end{tabular}
\\

\noindent \textbf{Veřejné metody:}\\
\begin{tabular} {|l|l|p{32mm}|p{58mm}|}
\hline
Název metody & Typ & Argumenty & Funkce\\
\hline
\hline
FindGUpgradeDataByUpId & -- & int upgradeId & Najde vlastněnou \hyperref[gupgradedata]{GUpgradeData} hodnotu dle zadaného upgrade id.\\
\hline
AddGUpgrade & -- & int upgradeId,\newline bool isUsed = false & Přidá vylepšení zbraně do gun upgrade inventáře. Pokud je isUsed true, je rovnou zapsáno jako aktuálně používané.\\
\hline
RemoveGUpgrade & -- & int upgradeId & Odebere vylepšení zbraně z gun upgrade inventáře.\\
\hline
UseGUpgrade & -- & int upgradeId & Navýší počet použitých vylepšení zbraně dle upgrade id v gun upgrade inventáři.\\
\hline
UnuseGUpgrade & -- & int upgradeId & Sníží počet použitých vylepšení zbraně dle upgrade id v gun upgrade inventáři.\\
\hline
\end{tabular}
\\

\subsection{Třída GUpgradeData} \label{gupgradedata}
\textbf{Účel:} Ukládá data spjatá s hráčem a jedním specifickým vylepšením.\\

\noindent \textbf{Veřejné proměnné:}\\
\begin{tabular} {|l|l|l|}
\hline
Název proměnné & Datový typ  & Popis\\
\hline
\hline
UpgradeId & int & Id hodnota vylepšení.\\
\hline
TotalCount & int & Celkový počet vlastněných vylepšení.\\
\hline
UsedCount & int & Počet aktuálně používaných vylepšení.\\
\hline
\end{tabular}
\\


\section{Tvorba herní mapy}
%Objekty na mapě, Item spawn, Player spawn, Terén a proces texturování terénu, voda, tráva, "vítr"

\subsection{Item spawn}

Náhodné rozmístění jednotlivých itemů po členitém terénu mapy je určováno ručně tvořenou heatmapou. Intenzita barevného kanálu určuje pravděpodobnost pro objevení itemu v dané souřadnici viz obrázek \ref{fig:itemspawnheatmap}.\\

\begin{figure}[h]
    \centering
    \includegraphics[width=0.3\linewidth]{images/other/itemSpawnHeatmap.png}
    \caption{Item spawn heatmapa}
    \label{fig:itemspawnheatmap}
\end{figure}

Samotnou hustotu a pravidelné rozmístění nám zprostředkovává poisson disc sampling algoritmus. Vizualizace poisson disc samplingu viz obrázek \ref{fig:poissonsampling}.

\begin{figure}[h]
    \centering
    \includegraphics[width=0.55\linewidth]{images/other/poissonDiscSampling.png}
    \caption{Ukázka jak funguje poisson disc sampling}
    \label{fig:poissonsampling}
\end{figure}

\FloatBarrier

Tyto 2 vrstvy přes sebe určují souřadnice X a Z, kde se instance objektu vytvoří. Vizualizováno v obrázku \ref{fig:itemspawnprogression}.

\begin{figure}[h]
    \centering
    \includegraphics[width=\linewidth]{images//other/itemSpawnProgression.png}
    \caption{Vizualizace vrstvení map}
    \label{fig:itemspawnprogression}
\end{figure}

K samotnému umístění však potřebujeme i třetí Y souřadnici. Tu potřebujeme určit takovým způsobem, aby se objekt objevil na "povrchu"\space terénu. Z každého místa proto vysíláme raycast s vektorem (0,-1,0) (směr dolů v herním prostoru) a vyhledáváme kolizi s objektem ve vrstvě "Terrain". Vizualizováno v obrázku \ref{fig:mapheatspawn}. Při zásahu zapíšeme získanou pozici a posuneme o 1 hodnotu na ose Y (nahoru) pro zamezení propadnutí terénem. Na výsledné pozici vytváříme instanci itemu. Itemu je nastavena náhodná rotace.

\begin{figure}[h]
    \centering
    \includegraphics[width=0.75\linewidth]{images//other/mapHeatSpawnArrows.png}
    \caption{Vizualizace promítnutí heatmapy na terén}
    \label{fig:mapheatspawn}
\end{figure}

\subsection{Rozmístění hráčů}

Pozice rozmístění hráčů na základní mapě určuje 8 ručně umístěných objektů. Při rozmístění hráčů se tyto pozice vybírají náhodně, však unikátně. Na 1 pozici může být právě 1 hráčská postava.

\section{Vlastní znovupoužitelné UI komponenty}

\subsection{NetworkSuccessBtn} \label{networksuccessbutton}

\textbf{Účel:} Slouží jakožto tlačítko, které vykoná akci pouze pokud bylo zakliknuto všemi připojenými klienty.\\
\textbf{Závislosti:} Vychází z \hyperlink{https://docs.unity3d.com/2018.2/Documentation/ScriptReference/UI.Button.html}{UnityEngine.UI Button}\cite{unity-button} komponenty a závisí na \href{https://docs-multiplayer.unity3d.com/netcode/current/basics/networkobject/}{NetworkObject}\cite{unity-netcode-networkobject} komponentě.\\
\textbf{Přidané funkce:}\\
\begin{tabular} {|l|l|p{100mm}|}
\hline
Název & Typ & Popis\\
\hline
\hline
OnServerFullfilled & UnityEvent & Je vyvoláno pouze na serveru, když server obdrží potvrzení o připravenosti od všech klientů.\\
\hline
OnPreFullfilled & UnityEvent & Je vyvoláno na nehostícím klientovi v momentu, kdy počet potvrzení o připravenosti odpovídá počtu klientů. Je vyvoláno před odesláním potvrzení o připravenosti na straně tohoto klienta na server. Slouží pro zpracování iluze responzivnosti na straně klienta.\\
\hline
\end{tabular}
\\
\subsection{NetworkCoundownTxt} \label{networkcountdowntext}

\textbf{Účel:} Slouží jakožto komponenta, která synchronizovaně zobrazuje odpočet u všech připojených klientů. Odpočet běží na serveru a jeho změny jsou odesílány ke klientům. Po dokončení odpočtu vyvolává event.\\
\textbf{Závislosti:} Závisí na \href{https://docs-multiplayer.unity3d.com/netcode/current/basics/networkobject/}{NetworkObject}\cite{unity-netcode-networkobject} komponentě.\\
\textbf{Přidané funkce:}\\
\begin{tabular} {|l|l|p{100mm}|}
\hline
Název & Typ & Popis\\
\hline
\hline
\_doneAction & UnityEvent & Je vyvoláno pouze na serveru když skončí odpočet.\\
\hline
\_timeLength & int & Určuje dobu odpočtu ve vteřinách.\\
\hline
\end{tabular}
\\

\section{Slovník užitých pojmů}
Instancovat - Vytvořit objekt v herní scéně z prefab objektu\label{dic:instancovat}\\
Spawnout - U objektu, který byl instancován na serveru, zavolá vytvoření instance téhož objektu u všech připojených klientů s propojením na originální objekt na serveru.\label{dic:spawn}\\



\include{sub/grafika}


\chapter*{Závěr}


Cílem projektu bylo vytvořit a navrhnout minimálně funkční verzi 3D multiplayerové hry Branch Brawl, což se také podařilo. Nicméně to vyžadovalo úpravy původního konceptu. Původní systém získávání itemů v průběhu kola na určitých mapách byl zrušen a nahrazen systémem výběru vylepšení a vylepšování zbraně mezi koly. Druhou změnou byl přechod z původního pohledu FPS na TPS za účelem lepší čitelnosti dění ve hře.\\

Obsahem práce bylo navržení, implementace a grafické ztvárnění první beta verze hry. Hra v současném stavu není sice finální, ale je již hratelná a poskytuje základy pro budoucí vývoj. Celkový systém zbraní (klacků) byl plně navržen a implementován tak, aby přidávání nových funkcí bylo co nejjednodušší. Aktuální stav hry je také obohacen o vlastnoručně vytvořenou grafiku, která spadá do obsahu projektové práce.\\

Vývoj projektu mě naučil způsobům vývoje nejen multiplayerových her, ale také mi poskytl zkušenosti s tvorbou rozsáhlých projektů od myšlenky po implementaci. Plánuji nadále rozvíjet projekt i v budoucích letech o nespočet nápadů, které jsem v tomto časovém úseku nedokázal do hry začlenit. Následně mám v plánu distribuci projektu na herní trh, včetně známé platformy Steam, po alespoň částečném dokončení hry.\\

% Literature
\pagebreak

\chapter*{Přílohy}
    
\begin{landscape}

\begin{figure}[h]
    \centering
    \includegraphics[width=\linewidth]{images/diagrams/cdAll.png}
    \caption{Diagram všech tříd}
    \label{fig:scenes}
\end{figure}

\begin{figure}[h]
    \centering
    \includegraphics[width=\linewidth]{images/diagrams/cdGunParts.png}
    \caption{Diagram tříd součástek zbraně}
    \label{fig:scenes}
\end{figure}

\begin{figure}[h]
    \centering
    \includegraphics[width=\linewidth]{images/diagrams/cdUpgrades.png}
    \caption{Diagram tříd vylepšení}
    \label{fig:scenes}
\end{figure}

\end{landscape}

\printbibliography[title={Literatura}]

\renewcommand{\listfigurename}{Obrázky, Grafy a Tabulky}
\listoffigures

\pagebreak

\end{document}